﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Reflection;
using System.Net.Security;
using System.IO;
using System.Collections;
using System.ComponentModel;

namespace CP.DBService
{
    public class PortalService
    {
        private static readonly string EntityAssemplyName = "CP.Entities";
        public static T CreateService<T>()
        {
            T instance = (T)Activator.CreateInstance(typeof(T));
            return instance;
        }

        public static object CreateService(string ServiceName)
        {
            string assemblyName = EntityAssemplyName;
            string service = EntityAssemplyName + "." + ServiceName;

            if (ServiceName.StartsWith(EntityAssemplyName, StringComparison.OrdinalIgnoreCase))
            {
                assemblyName = ServiceName.Substring(0, ServiceName.LastIndexOf("."));
                service = ServiceName;
            }

            Assembly assembly = Assembly.Load(assemblyName);
            object instance = Activator.CreateInstance(assembly.GetType(service, true, true));
            return instance;

        }

        public static object CreateEntity(string entityName)
        {
            string assemblyName = EntityAssemplyName;
            string entity = assemblyName + "." + entityName;

            if (entityName.StartsWith(EntityAssemplyName, StringComparison.OrdinalIgnoreCase))
            {
                assemblyName = entityName.Substring(0, entityName.LastIndexOf("."));
                entity = entityName;
            }

            Assembly assembly = Assembly.Load(assemblyName);
            object instance = Activator.CreateInstance(assembly.GetType(entityName, true, true));
            return instance;

        }

        public static object InvokeMethod<TService>(string method, object[] parameters)
        {
            TService serviceObj = CreateService<TService>();
            return InvokeServiceMethod(serviceObj, typeof(TService).Name, method, parameters);
        }

        public static object InvokeMethod(string service, string method, object[] parameters)
        {
            if (!service.EndsWith("Service"))
                service += "Service";
            object serviceObj = CreateService(service);
            return InvokeServiceMethod(serviceObj, service, method, parameters);
        }

        public static object InvokeFrameworkMethod(string service, string method, object[] parameters)
        {
            string assemblyName = EntityAssemplyName;
            if (service.StartsWith(EntityAssemplyName, StringComparison.OrdinalIgnoreCase))
            {
                assemblyName = service.Substring(0, service.LastIndexOf("."));
            }
            Assembly assembly = Assembly.Load(assemblyName);

            object serviceObj = Activator.CreateInstance(assembly.GetType(assemblyName + "." + service, true, true));
            return InvokeServiceMethod(serviceObj, service, method, parameters);
        }

        /// <summary>
        /// common method for invoke
        /// </summary>
        /// <param name="serviceObj"></param>
        /// <param name="method"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private static object InvokeServiceMethod(object serviceObj, string service, string method, object[] parameters)
        {
            var invokeMethod = serviceObj.GetType().GetMethod(method);

            if (invokeMethod != null)
            {
                //处理函数参数
                IList<object> parameterList = null;
                if (parameters != null)
                {
                    parameterList = new List<object>();

                    //判断参数个数是否相等
                    var methodParameters = invokeMethod.GetParameters();
                    if (parameters.Count() != methodParameters.Count())
                        throw new Exception(string.Format("{0}调用的方法{1}有{2}个参数，您在调用时使用了{3}个参数。参数个数不匹配，请确认。", service, method, methodParameters.Count(), parameters.Count()));

                    //转换参数数据类型
                    int parameterIndex = 0;
                    foreach (var parameter in methodParameters)
                    {
                        object newParameter = null;
                        if (parameter.ParameterType.IsClass)//如果是Class数据类型不需要转换
                            newParameter = parameters[parameterIndex];
                        else
                            newParameter = TypeDescriptor.GetConverter(parameter.ParameterType).ConvertTo(parameters[parameterIndex], parameter.ParameterType);
                        parameterList.Add(newParameter);
                        parameterIndex++;
                    }
                }

                //调用函数

                object retValue = invokeMethod.Invoke(serviceObj, parameterList == null ? null : parameterList.ToArray());

                //返回数据
                return retValue;
            }
            else
            {
                throw new Exception(string.Format("{0}没有方法{1}，执行失败。请确认WCF后台方法。", service, method));
            }
        }
    }
}

